package live.zs.securitytokenlocal.security;


import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.interfaces.DecodedJWT;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.userdetails.User;
import org.springframework.stereotype.Component;

import java.util.Date;
import java.util.List;

/**
 * @author madison
 * @description
 * @date 2021/7/16 22:03
 */
@Slf4j
@Component
public class JwtTokenManager {

    @Value("${auth.token.secret.key:secret}")
    private String secret;
    @Value("${auth.token.expire.seconds:18000}")
    private Long expiration;

    /**
     * Create token.
     *
     * @param authentication auth info
     * @return token
     */
    public String createToken(Authentication authentication) {
        return createToken(authentication.getName());
    }

    /**
     * Create and Sign a Token
     *
     * @param userName auth info
     * @return token
     */
    public String createToken(String userName) {

        long now = System.currentTimeMillis();
        Date validity = new Date(now + expiration * 1000L);
        Algorithm algorithm = Algorithm.HMAC512(secret);
        //HMAC
        String token = JWT.create()
                .withSubject(userName)
                .withIssuer("auth0")
                .withExpiresAt(validity)
                .sign(algorithm);
        return token;
    }

    /**
     * Get auth Info.
     *
     * @param token token
     * @return auth info
     */
    public Authentication getAuthentication(String token) {
        DecodedJWT jwt = JWT.decode(token);

        List<GrantedAuthority> authorities = AuthorityUtils.createAuthorityList();

        User principal = new User(jwt.getSubject(), "", authorities);
        return new UsernamePasswordAuthenticationToken(principal, "", authorities);
    }

    /**
     * validate token.
     *
     * @param token token
     */
    public void validateToken(String token) {
        Algorithm algorithm = Algorithm.HMAC512(secret);
        JWTVerifier verifier = JWT.require(algorithm)
                .withIssuer("auth0")
                .build();
        DecodedJWT verify = verifier.verify(token);
        log.warn("verify info:{}", verify);
    }
}
